#pragma once
#include  "qcontrol.h"

#include  <shlwapi.h>

namespace micro{

namespace gui
{

class QEdit: public QControl
{
public:
	QEdit(HWND h = nullptr);
	virtual ~QEdit(void);


	virtual bool Create(QWindow *parent, int id=0, UINT style=0);
	
	virtual bool OnPreCreate(CREATESTRUCT& cs);





	virtual LPCTSTR GetWndClassName()
	{
		return _T("EDIT");
	}

	BOOL CanUndo() const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_CANUNDO, 0, 0L);
	}

	void AutoComplete(DWORD flags=SHACF_FILESYSTEM)
	{
		::SHAutoComplete( _window,  flags);
	}

	int GetLineCount() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, EM_GETLINECOUNT, 0, 0L);
	}

	BOOL GetModify() const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_GETMODIFY, 0, 0L);
	}

	void SetModify(BOOL bModified = TRUE)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETMODIFY, bModified, 0L);
	}

	void GetRect(LPRECT lpRect) const
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_GETRECT, 0, (LPARAM)lpRect);
	}

	DWORD GetSel() const
	{
		ASSERT(::IsWindow(_window));
		return (DWORD)::SendMessage(_window, EM_GETSEL, 0, 0L);
	}

	void GetSel(int& nStartChar, int& nEndChar) const
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar);
	}

#ifndef _WIN32_WCE
	HLOCAL GetMemHandle() const
	{
		ASSERT(::IsWindow(_window));
		return (HLOCAL)::SendMessage(_window, EM_GETHANDLE, 0, 0L);
	}

	void SetMemHandle(HLOCAL hBuffer)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETHANDLE, (WPARAM)hBuffer, 0L);
	}
#endif // !_WIN32_WCE

	DWORD GetMargins() const
	{
		ASSERT(::IsWindow(_window));
		return (DWORD)::SendMessage(_window, EM_GETMARGINS, 0, 0L);
	}

	void SetMargins(UINT nLeft, UINT nRight)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(nLeft, nRight));
	}

	UINT GetLimitText() const
	{
		ASSERT(::IsWindow(_window));
		return (UINT)::SendMessage(_window, EM_GETLIMITTEXT, 0, 0L);
	}

	void SetLimitText(UINT nMax)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETLIMITTEXT, nMax, 0L);
	}

	POINT PosFromChar(UINT nChar) const
	{
		ASSERT(::IsWindow(_window));
		DWORD dwRet = (DWORD)::SendMessage(_window, EM_POSFROMCHAR, nChar, 0);
		POINT point = { ((int)(short)LOWORD(dwRet)), ((int)(short)HIWORD(dwRet)) };
		return point;
	}

	int CharFromPos(POINT pt, int* pLine = nullptr) const
	{
		ASSERT(::IsWindow(_window));
		DWORD dwRet = (DWORD)::SendMessage(_window, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
		if(pLine != nullptr)
			*pLine = (int)(short)HIWORD(dwRet);
		return (int)(short)LOWORD(dwRet);
	}

	// NOTE: first word in lpszBuffer must contain the size of the buffer!
	int GetLine(int nIndex, LPTSTR lpszBuffer) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
	}

	int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
	{
		ASSERT(::IsWindow(_window));
		*(LPWORD)lpszBuffer = (WORD)nMaxLength;
		return (int)::SendMessage(_window, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
	}

	TCHAR GetPasswordChar() const
	{
		ASSERT(::IsWindow(_window));
		return (TCHAR)::SendMessage(_window, EM_GETPASSWORDCHAR, 0, 0L);
	}

	void SetPasswordChar(TCHAR ch)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETPASSWORDCHAR, ch, 0L);
	}

#ifndef _WIN32_WCE
	EDITWORDBREAKPROC GetWordBreakProc() const
	{
		ASSERT(::IsWindow(_window));
		return (EDITWORDBREAKPROC)::SendMessage(_window, EM_GETWORDBREAKPROC, 0, 0L);
	}

	void SetWordBreakProc(EDITWORDBREAKPROC ewbprc)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETWORDBREAKPROC, 0, (LPARAM)ewbprc);
	}
#endif // !_WIN32_WCE

	int GetFirstVisibleLine() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, EM_GETFIRSTVISIBLELINE, 0, 0L);
	}

#ifndef _WIN32_WCE
	int GetThumb() const
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetStyle() & ES_MULTILINE) != 0);
		return (int)::SendMessage(_window, EM_GETTHUMB, 0, 0L);
	}
#endif // !_WIN32_WCE

	BOOL SetReadOnly(BOOL bReadOnly = TRUE)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_SETREADONLY, bReadOnly, 0L);
	}

#if (WINVER >= 0x0500) && !defined(_WIN32_WCE)
	UINT GetImeStatus(UINT uStatus) const
	{
		ASSERT(::IsWindow(_window));
		return (UINT)::SendMessage(_window, EM_GETIMESTATUS, uStatus, 0L);
	}

	UINT SetImeStatus(UINT uStatus, UINT uData)
	{
		ASSERT(::IsWindow(_window));
		return (UINT)::SendMessage(_window, EM_SETIMESTATUS, uStatus, uData);
	}
#endif // (WINVER >= 0x0500) && !defined(_WIN32_WCE)

#if (_WIN32_WINNT >= _WIN32_WINNT_WIN7) //0x0501
 
	int SetCueBanner(LPCTSTR lParam, BOOL wParam = FALSE)
	{
		ASSERT(::IsWindow(_window));
		return (int)SendMessage( EM_SETCUEBANNER, (WPARAM) (BOOL) wParam,(LPARAM) lParam );  
	}
	BOOL GetCueBannerText(LPCWSTR lpstrText, int cchText) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_GETCUEBANNER, (WPARAM)lpstrText, cchText);
	}

	//// bKeepWithFocus - Vista only
	//BOOL SetCueBannerText(LPCWSTR lpstrText, BOOL bKeepWithFocus = FALSE)
	//{
	//	ASSERT(::IsWindow(_window));
	//	return (BOOL)::SendMessage(_window, EM_SETCUEBANNER, (WPARAM)bKeepWithFocus, (LPARAM)(lpstrText));
	//}
#endif // (_WIN32_WINNT >= 0x0501)

// Operations
	void EmptyUndoBuffer()
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_EMPTYUNDOBUFFER, 0, 0L);
	}

	BOOL FmtLines(BOOL bAddEOL)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_FMTLINES, bAddEOL, 0L);
	}

	void LimitText(int nChars = 0)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_LIMITTEXT, nChars, 0L);
	}

	int LineFromChar(int nIndex = -1) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, EM_LINEFROMCHAR, nIndex, 0L);
	}

	int LineIndex(int nLine = -1) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, EM_LINEINDEX, nLine, 0L);
	}

	int LineLength(int nLine = -1) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, EM_LINELENGTH, nLine, 0L);
	}

	void LineScroll(int nLines, int nChars = 0)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_LINESCROLL, nChars, nLines);
	}

	void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo = FALSE)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
	}

	void SetRect(LPCRECT lpRect)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETRECT, 0, (LPARAM)lpRect);
	}

	void SetRectNP(LPCRECT lpRect)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETRECTNP, 0, (LPARAM)lpRect);
	}

	void SetSel(DWORD dwSelection, BOOL bNoScroll = FALSE)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETSEL, LOWORD(dwSelection), HIWORD(dwSelection));
		if(!bNoScroll)
			::SendMessage(_window, EM_SCROLLCARET, 0, 0L);
	}


	// The higher value specifies the position of the first character beyond the selection.
	void SetSel(int nStartChar, int nEndChar, BOOL bNoScroll = FALSE)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETSEL, nStartChar, nEndChar);
		if(!bNoScroll)
			::SendMessage(_window, EM_SCROLLCARET, 0, 0L);
	}

	void SetSelAll(BOOL bNoScroll = FALSE)
	{
		SetSel(0, -1, bNoScroll);
	}

	void SetSelNone(BOOL bNoScroll = FALSE)
	{
		SetSel(-1, 0, bNoScroll);
	}

	BOOL SetTabStops(int nTabStops, LPINT rgTabStops)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
	}

	BOOL SetTabStops()
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_SETTABSTOPS, 0, 0L);
	}

	BOOL SetTabStops(const int& cxEachStop)    // takes an 'int'
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
	}

	void ScrollCaret()
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SCROLLCARET, 0, 0L);
	}

	int Scroll(int nScrollAction)
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetStyle() & ES_MULTILINE) != 0);
		LRESULT lRet = ::SendMessage(_window, EM_SCROLL, nScrollAction, 0L);
		if(!(BOOL)HIWORD(lRet))
			return -1;   // failed
		return (int)(short)LOWORD(lRet);
		
	}

	void InsertText(int nInsertAfterChar, LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
	{
		SetSel(nInsertAfterChar, nInsertAfterChar, bNoScroll);
		ReplaceSel(lpstrText, bCanUndo);
	}

	void AppendText(LPCTSTR lpstrText, BOOL bNoScroll = FALSE, BOOL bCanUndo = FALSE)
	{
		InsertText(GetTextLength(), lpstrText, bNoScroll, bCanUndo);
	}

#if (_WIN32_WINNT >= 0x0501)
	BOOL ShowBalloonTip(PEDITBALLOONTIP pEditBaloonTip)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_SHOWBALLOONTIP, 0, (LPARAM)pEditBaloonTip);
	}

	BOOL HideBalloonTip()
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_HIDEBALLOONTIP, 0, 0L);
	}
#endif // (_WIN32_WINNT >= 0x0501)

#if (_WIN32_WINNT >= 0x0600)
	DWORD GetHilite() const
	{
		ASSERT(::IsWindow(_window));
		return (DWORD)::SendMessage(_window, EM_GETHILITE, 0, 0L);
	}

	void GetHilite(int& nStartChar, int& nEndChar) const
	{
		ASSERT(::IsWindow(_window));
		DWORD dwRet = (DWORD)::SendMessage(_window, EM_GETHILITE, 0, 0L);
		nStartChar = (int)(short)LOWORD(dwRet);
		nEndChar = (int)(short)HIWORD(dwRet);
	}

	void SetHilite(int nStartChar, int nEndChar)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, EM_SETHILITE, nStartChar, nEndChar);
	}
#endif // (_WIN32_WINNT >= 0x0600)

	// Clipboard operations
	BOOL Undo()
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, EM_UNDO, 0, 0L);
	}

	void Clear()
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, WM_CLEAR, 0, 0L);
	}

	void Copy()
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, WM_COPY, 0, 0L);
	}

	void Cut()
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, WM_CUT, 0, 0L);
	}

	void Paste()
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, WM_PASTE, 0, 0L);
	}

#ifdef WIN32_PLATFORM_WFSP   // SmartPhone only messages
	DWORD GetExtendedStyle()
	{
		return SendMessage(EM_GETEXTENDEDSTYLE);
	}

	DWORD SetExtendedStyle(DWORD dwMask, DWORD dwExStyle)
	{
		return SendMessage(EM_SETEXTENDEDSTYLE, (WPARAM)dwMask, (LPARAM)dwExStyle);
	}

	DWORD GetInputMode(BOOL bCurrentMode = TRUE)
	{
		return SendMessage(EM_GETINPUTMODE, 0, (LPARAM)bCurrentMode);
	}

	BOOL SetInputMode(DWORD dwMode)
	{
		return SendMessage(EM_SETINPUTMODE, 0, (LPARAM)dwMode);
	}

	BOOL SetSymbols(LPCTSTR szSymbols)
	{
		return SendMessage(EM_SETSYMBOLS, 0, (LPARAM)szSymbols);
	}

	BOOL ResetSymbols()
	{
		return SendMessage(EM_SETSYMBOLS);
	}
#endif // WIN32_PLATFORM_WFSP
	 
};

 

}//namespace

}//micro